package wili.a;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 功能：find(att,value, objs), print(objs), pintDiffer(obj1, obj2) <br>
 * 在断点处执行此方法即可：a.obj9.find("",obj);
 *
 * @author weila 2022年6月16日
 */
public class Obj9 {
	public static boolean PrintNull = false;
	public static boolean USE = "".isEmpty();// 若debug时修改代码不生效，此变量值可方便开关。

	static boolean PrintID = "asdf".isEmpty();

	static int times;

	public static int maxDiffNum = 10, incID;

	static String findName = "", findValue = "";// debug时或能据此加断点。

	public static interface Act {
		String find = "find", print = "print", printDiff = "printDiff";
	}

	public static String curAction;

	public static void use(int opt) {
		if (opt == 1) {
			USE = true;
		} else {
			USE = false;
		}
	}

	/**
	 * Find attribute with given name and value deep into objs. 一般用来支持大批量拦截。
	 *
	 * @name empty name mean every name.
	 * @value empty value means every value.
	 */
	public static boolean find(String name, String value, Object... objs) {
		if ("456".isEmpty())
			return false;
		if (!USE || name.isEmpty() && value.isEmpty())
			return false;
		AttValueFinder find = new AttValueFinder(objs);
		if (find.find(name, value)) {
			return true;
		}
		return false;
	}

	/**
	 * @param obj
	 * @return
	 */
	private static String prettyStringOf(Object obj) {
		Map<Object, Integer> skipMap = new HashMap<>();
		StringBuilder toBuf = new StringBuilder();
		Obj9a.findOrPrint00("", "", "", obj, skipMap, toBuf);
		return toBuf.toString();
	}

	/**
	 * Print content of object one by one..
	 */
	public synchronized static void print(Object... objs) {
		if (!USE)
			return;
		PrintID = true;
		incID = 0;
		Map<Object, Integer> skipMap = new HashMap<>();
		for (Object obj : objs) {
			String name = obj.getClass().getSimpleName();
			Obj9a.findOrPrint00(Act.print, "", name, obj, skipMap, null);
		}
		Obj9a.log("end. lineNum" + times);
		return;
	}

	/**
	 * Print different content of object aa & bb..
	 */
	public static void printDiff(Object aa, Object bb) {
		if (!USE)
			return;
		PrintID = false;
		String st1 = prettyStringOf(aa), st2 = prettyStringOf(bb);
		String[] tt1 = st1.split("\\s*\n\\s*");
		String[] tt2 = st2.split("\\s*\n\\s*");
		int times = 0;
		Obj9a.log("==========printDiff:");
		int min = Math.min(tt1.length, tt2.length);
		for (int i = 0; i < min; i++) {
			if (!tt1[i].equals(tt2[i])) {
				++times;
				Obj9a.log("\n" + times + ": " + tt1[i] + ", @line" + i);
				Obj9a.log("" + times + ": " + tt2[i]);
				if (times >= maxDiffNum) {
					Obj9a.log("......" + (tt1.length - tt2.length) + " lines not check.");
					break;
				}
			}
		}
		if (tt1.length > tt2.length) {
			Obj9a.log(">>> aa is longer:");
			for (int i = tt2.length; i < tt1.length; i++) {
				++times;
				Obj9a.log(times + ": " + tt1[i] + ", @line" + i + " of aa.");
				if (times >= maxDiffNum) {
					Obj9a.log("......" + (tt1.length - tt2.length) + " lines left.");
					break;
				}
			}
		} else if (tt1.length < tt2.length) {
			Obj9a.log(">>> bb is longer:");
			for (int i = tt1.length; i < tt2.length; i++) {
				Obj9a.log(times + ": " + tt2[i] + ", @line" + i + " of bb.");
				if (++times >= maxDiffNum) {
					Obj9a.log("......" + (tt2.length - tt1.length) + " lines left.");
					break;
				}
			}
		}
		if (times == 0) {
			Obj9a.log("Diff not found.");
		}
		Obj9a.log("==========printDiff:end.");
	}

	static void pause() {
	}

	static abstract class Bean {
		String name = "xiong";

		int[] aa = { 100, 45 };
	}

	static class Bean2 extends Bean {
		boolean isTrue = false;
	}

	@SuppressWarnings("all")
	static void test() {
		int opt = 1;
		//opt = 2;
		Map map = new HashMap<>();
		map.put("jack", 11);
		map.put("tom", 22);
		map.put("name", "bab");
		List<Object> lis = Arrays.asList(11, "eng", "hello", map, new Bean2(), map);
		if (opt == 1) {
			Obj9.print(lis);
		} else {
			List<Object> lis2 = new ArrayList<>(Arrays.asList(11, "eng1", "hello2", map, new Bean2(), map));
			lis2.add(100);
			Obj9.printDiff(lis, lis2);
		}
	}

	public static void main(String[] args) {
		USE = true;
		test();
	}
}
